using AutoMapper;
using UwinEducation.Application.Common.Interfaces;
using UwinEducation.Application.Dtos;
using UwinEducation.Domain.Entities;
using UwinEducation.Shared.Models;
using Microsoft.EntityFrameworkCore;
using UwinEducation.Infrastructure.Persistence;
using UwinEducation.Domain.IRepositories;

namespace UwinEducation.Application.Services
{
    /// <summary>
    /// 教师档期服务实现
    /// </summary>
    public class TeacherAvailabilityService : ITeacherAvailabilityService
    {
        private readonly ITeacherAvailabilityRepository _teacherAvailabilityRepository;
        private readonly ITeacherRepository _teacherRepository;
        private readonly IMapper _mapper;
        private readonly ApplicationDbContext _context;

        public TeacherAvailabilityService(
            ITeacherAvailabilityRepository teacherAvailabilityRepository,
            ITeacherRepository teacherRepository,
            ApplicationDbContext context,
            IMapper mapper)
        {
            _teacherAvailabilityRepository = teacherAvailabilityRepository;
            _teacherRepository = teacherRepository;
            _context = context;
            _mapper = mapper;
        }

        public async Task<PagedResult<TeacherAvailabilityDto>> GetPagedListAsync(TeacherAvailabilityPageRequest pageRequest)
        {
            var result = await _teacherAvailabilityRepository.GetPagedListAsync(pageRequest);
            return new PagedResult<TeacherAvailabilityDto>
            {
                Total = result.Total,
                Items = _mapper.Map<List<TeacherAvailabilityDto>>(result.Items)
            };
        }

        /// <summary>
        /// 获取教师档期分页列表（按是否有排课排序）
        /// </summary>
        public async Task<PagedResult<TeacherAvailabilityDto>> GetPagedListWithScheduleStatusAsync(TeacherAvailabilityPageRequest pageRequest)
        {
            var result = await _teacherAvailabilityRepository.GetPagedListWithScheduleStatusAsync(pageRequest);
            return new PagedResult<TeacherAvailabilityDto>
            {
                Total = result.Total,
                Items = _mapper.Map<List<TeacherAvailabilityDto>>(result.Items)
            };
        }

        public async Task<TeacherAvailabilityDto> GetByIdAsync(Guid id)
        {
            var availability = await _teacherAvailabilityRepository.GetDetailsByIdAsync(id);
            if (availability == null)
            {
                throw new ArgumentException($"教师档期不存在: {id}");
            }

            return _mapper.Map<TeacherAvailabilityDto>(availability);
        }

        public async Task<TeacherAvailabilityDto> CreateAsync(CreateTeacherAvailabilityDto input)
        {
            //// 验证教师是否存在
            //var teacher = await _teacherRepository.GetByIdAsync(input.TeacherId);
            //if (teacher == null)
            //{
            //    throw new ArgumentException($"教师不存在: {input.TeacherId}");
            //}

            //// 检查时间冲突
            //var hasConflict = await _teacherAvailabilityRepository.HasTimeConflictAsync(
            //    input.TeacherId,
            //    input.StartDate,
            //    input.EndDate,
            //    input.DayOfWeek,
            //    input.StartTime,
            //    input.EndTime,
            //    input.Id);

            //if (hasConflict)
            //{
            //    throw new ArgumentException("该时间段已有其他档期安排");
            //}

            //var availability = TeacherAvailability.Create(
            //    input.TeacherId,
            //    input.StartDate,
            //    input.EndDate,
            //    input.DayOfWeek,
            //    input.StartTime,
            //    input.EndTime,
            //    input.Remarks??string.Empty);

            //await _teacherAvailabilityRepository.AddAsync(availability);
            //return await GetByIdAsync(availability.Id);

            return null;
        }

        public async Task<TeacherAvailabilityDto> UpdateAsync(UpdateTeacherAvailabilityDto input)
        {
            var availability = await _teacherAvailabilityRepository.GetByIdAsync(input.Id);
            if (availability == null)
            {
                throw new ArgumentException($"教师档期不存在: {input.Id}");
            }

            if (input.StartDate.HasValue || input.EndDate.HasValue || input.DayOfWeek.HasValue || 
                input.StartTime.HasValue || input.EndTime.HasValue)
            {
                var hasConflict = await _teacherAvailabilityRepository.HasTimeConflictAsync(
                    availability.TeacherId,
                    input.StartDate ?? availability.StartDate,
                    input.EndDate ?? availability.EndDate,
                    input.DayOfWeek ?? availability.DayOfWeek ?? 1,
                    input.StartTime ?? availability.StartTime ?? TimeSpan.Zero,
                    input.EndTime ?? availability.EndTime ?? TimeSpan.Zero,
                    input.Id);

                if (hasConflict)
                {
                    throw new ArgumentException("该时间段已有其他档期安排");
                }
            }

            availability.StartDate = input.StartDate ?? availability.StartDate;
            availability.EndDate = input.EndDate ?? availability.EndDate;
            availability.DayOfWeek = input.DayOfWeek ?? availability.DayOfWeek;
            availability.StartTime = input.StartTime ?? availability.StartTime;
            availability.EndTime = input.EndTime ?? availability.EndTime;
            availability.Remarks = input.Remarks ?? availability.Remarks;
            availability.CourseType = input.CourseType ?? availability.CourseType;

            await _teacherAvailabilityRepository.UpdateAsync(availability);
            return await GetByIdAsync(availability.Id);
        }

        public async Task DeleteAsync(Guid id)
        {
            var availability = await _teacherAvailabilityRepository.GetByIdAsync(id);
            if (availability == null)
            {
                throw new ArgumentException($"教师档期不存在: {id}");
            }

            await _teacherAvailabilityRepository.DeleteAsync(id);
        }

        public async Task<BatchCreateTeacherAvailabilityDto> GetByTeacherIdAsync(Guid teacherId)
        {
            var availabilities = await _teacherAvailabilityRepository.GetByTeacherIdAsync(teacherId);
            if (availabilities == null || availabilities.Count == 0)
            {
                return new BatchCreateTeacherAvailabilityDto
                {
                    TeacherId = teacherId,
                    Availabilities = new List<CreateTeacherAvailabilityDto>()
                };
            }
            return new BatchCreateTeacherAvailabilityDto
            {
                TeacherId = teacherId,
                Availabilities = _mapper.Map<List<CreateTeacherAvailabilityDto>>(availabilities)
            };

            //return new BatchCreateTeacherAvailabilityDto
            //{
            //    TeacherId = teacherId,
            //    Availabilities = _mapper.Map<List<CreateTeacherAvailabilityDto>>(availabilities)
            //};

            //return _mapper.Map<List<TeacherAvailabilityDto>>(availabilities);
        }

        public async Task<List<TeacherAvailabilityDto>> GetByDateRangeAsync(Guid teacherId, DateTime startDate, DateTime endDate)
        {
            var availabilities = await _teacherAvailabilityRepository.GetByDateRangeAsync(teacherId, startDate, endDate);
            return _mapper.Map<List<TeacherAvailabilityDto>>(availabilities);
        }

        public async Task<List<TeacherAvailabilityDto>> BatchCreateAsync(BatchCreateTeacherAvailabilityDto inputs)
        {
            // 验证教师是否存在
            var teacher = await _teacherRepository.GetByIdAsync(inputs.TeacherId);
            if (teacher == null)
            {
                throw new ArgumentException($"教师不存在: {inputs.TeacherId}");
            }

            // 创建新档期
            //判断inputs.Availabilities 是否存在或者为空
            List<TeacherAvailability> availabilities = new List<TeacherAvailability>();
            if (inputs.Availabilities != null && inputs.Availabilities.Count > 0)
            {
                availabilities = inputs.Availabilities.Select(input => TeacherAvailability.Create(
                    inputs.TeacherId,
                    input.StartDate,
                    input.EndDate,
                    input.CourseType,
                    input.Remarks ?? string.Empty
                )).ToList();
            }
            // 使用事务确保操作的原子性
            using (var transaction = await _context.Database.BeginTransactionAsync())
            {
                try
                {
                    // 删除教师现有档期
                    await _teacherAvailabilityRepository.DeleteByTeacherIdAsync(inputs.TeacherId);

                    // 批量添加新档期
                    if (availabilities != null && availabilities.Count > 0)
                        await _teacherAvailabilityRepository.AddRangeAsync(availabilities);

                    // 提交事务
                    await transaction.CommitAsync();
                }
                catch (Exception ex)
                {
                    // 发生异常时回滚事务
                    await transaction.RollbackAsync();
                    throw;
                }
            }

            // 返回新创建的档期列表
            return _mapper.Map<List<TeacherAvailabilityDto>>(availabilities);
        }
    }
} 